from Tkinter import *
from Canvas import *
import sys
import random
##import HomVec3
import math

WIDTH  = 400 # width of canvas
HEIGHT = 400 # height of canvas

HPSIZE = 1 # double of point size (must be integer)
COLOR = "#0000FF" # blue

NOPOINTS = 1000

objectFile = "cow_points.raw"

tp = []
pointList = [] # list of points (used by Canvas.delete(...))

def quit(root=None):
    """ quit programm """
    if root==None:
        sys.exit(0)
    root._root().quit()
    root._root().destroy()

def draw():
  """ draw points """
    #for i in range(1,NOPOINTS):
	#x, y = random.randint(1,WIDTH), random.randint(1,HEIGHT)
  # project transformed points
   
  pp = [ p[:2]for p in tp]
    
  #transform to viewpoint
  vp = [[(p[0]+1)*WIDTH/2.0, (1-p[1])*HEIGHT/2.0] for p in pp]
  
  for p in vp:
    x,y = p
    p = can.create_oval(x-HPSIZE, y-HPSIZE, x+HPSIZE, y+HPSIZE, fill=COLOR, outline=COLOR)
    pointList.insert(0,p)

def rotYp():
    """ rotate counterclockwise around y axis """

    global tp
    angle = 10*math.pi/180
    tp = [[math.cos(angle)*p[0]-math.sin(angle)*p[2], p[1], math.sin(angle)*p[0]+math.cos(angle)*p[2]] for p in tp] 
    
    can.delete(*pointList)
    draw()

def rotYn():
    """ rotate clockwise around y axis """
    
    global tp
    angle = -10*math.pi/180
    tp = [[math.cos(angle)*p[0]-math.sin(angle)*p[2], p[1], math.sin(angle)*p[0]+math.cos(angle)*p[2]] for p in tp]
    can.delete(*pointList)
    draw()

# calculates the Edgepoints of the boundingBox
def calculateBoundingBox():
  xmin = float('inf')
  xmax = float('-inf')
  ymin = float('inf')
  ymax = float('-inf')
  zmin = float('inf')
  zmax = float('-inf')
  
  objectPointFile = "bunny_points.raw"
  f = open(objectPointFile)
  
  for line in f.readlines():
    points = line.split(" ")
    print points[0], points[1], points[2]
    if float(points[0]) < xmin: xmin = float(points[0]) 
    if float(points[0]) > xmax: xmax = float(points[0]) 
    if float(points[1]) < ymin: ymin = float(points[1]) 
    if float(points[1]) > ymax: ymax = float(points[1]) 
    if float(points[2]) < zmin: zmin = float(points[2]) 
    if float(points[2]) > zmax: zmax = float(points[2]) 
    
  return [(xmin, ymin, zmin), (xmax, ymax, zmax)]



def moveNewCoordinate(tup, move):
    return (tup[0] - move[0], tup[1] - move[1], tup[2] - move[2])


def scaleNewCoordinate(tup, scale):
    return (tup[0] / scale[0], tup[1] / scale[1], tup[2] / scale[2])
  
  
# moves center of boundingbox to the origin (0,0,0)
def moveCenterToOrigin(oldBoundingBox):
  xcen = (oldBoundingBox[0][0] + oldBoundingBox[1][0]) / 2.
  ycen = (oldBoundingBox[0][1] + oldBoundingBox[1][1]) / 2.
  zcen = (oldBoundingBox[0][2] + oldBoundingBox[1][2]) / 2.
  move = (xcen, ycen, zcen)
  print "Center:", move
  
  boundingBox = []
  for point in oldBoundingBox:
    boundingBox.append(moveNewCoordinate(point, move))
    
  return boundingBox
    
  
#def scaleBoundingBoxToCanonical(oldBoundingBox):
  #scale = 2/max(
  
  
  print "Scale Parameter:", scale
  
  boundingBox = []
  for point in oldBoundingBox[1:]:
    boundingBox.append(scaleNewCoordinate(point, scale))
    
  return boundingBox

def transformToXYArea(boundingBox):
  xyPoints = []
  for point in boundingBox:
    xyPoints.append((point[0], point[1]))
    
  return xyPoints
  

if __name__ == "__main__":
    #check parameters
    #if len(sys.argv) != 1:
       #print "pointViewerTemplate.py"
       #sys.exit(-1)
    if len(sys.argv) > 1:
      objectFile = sys.argv[1]

    # Punkte einlesen
    points = [ map(float, l.split()) for l in file(objectFile) ]
    
    # BoundingBox berechnen
    bb = [ map(min, zip(*points)), map(max, zip(*points)) ]
    print bb
    # Center of BB
    center = [(x[0]+x[1])/2.0 for x in zip(*bb)]
    
    #Calculate scalefactor
    scale = 2.0/max([(x[1]-x[0]) for x in zip(*bb)])
    
    # transform points to cannonical view volume
    tp = [[ (p[0]-center[0])*scale, (p[1]-center[1])*scale, (p[2]-center[2])*scale] for p in points]
    
    
        
    # create BoundingBox
    #boundingBox = calculateBoundingBox()
    #print "BoundingBox:", boundingBox
    #boundingBox = moveCenterToOrigin(boundingBox)
    #print "Moved BoundingBox:", boundingBox
    #boundingBox = scaleBoundingBoxToCanonical(boundingBox)
    #print "Scaled BoundingBox:", boundingBox
    #xyPoints = transformToXYArea(boundingBox)
    #print "XY-Area:", xyPoints
    
    

    # create main window
    mw = Tk()

    # create and position canvas and buttons
    cFr = Frame(mw, width=WIDTH, height=HEIGHT, relief="sunken", bd=1)
    cFr.pack(side="top")
    can = Canvas(cFr, width=WIDTH, height=HEIGHT)
    can.pack()
    bFr = Frame(mw)
    bFr.pack(side="left")
    bRotYn = Button(bFr, text="<-", command=rotYn)
    bRotYn.pack(side="left")
    bRotYp = Button(bFr, text="->", command=rotYp)
    bRotYp.pack(side="left")
    eFr = Frame(mw)
    eFr.pack(side="right")
    bExit = Button(eFr, text="Quit", command=(lambda root=mw: quit(root)))
    bExit.pack()

    # draw points
    draw()

    # start
    mw.mainloop()
    

    
